// 12.1.3 主模板
// 在C++模板系统中，"主模板"（Primary Template）是一个重要的概念，它是模板特化和偏特化的基础。以下是关于主模板的详细解释：

// 主模板的定义
// 主模板是最一般形式的模板声明，它为所有可能的模板参数提供通用实现：

// 类模板的主模板
template <typename T>
class Container
{
    // 通用实现...
};

// 函数模板的主模板
template <typename T>
T max(T a, T b)
{
    return a < b ? b : a;
}

// 主模板的特点
// 1.完整的参数列表：主模板必须声明所有模板参数，没有默认值的参数必须由用户提供
// 2.通用实现：主模板提供适用于任何有效模板参数的实现
// 3.可以被特化：主模板可以有完全特化和偏特化版本
// 4.必须先声明：在声明任何特化之前，必须先声明主模板

// 主模板与特化的关系
// 主模板与其特化形成一个家族：
// 主模板
template <typename T, typename U>
class Pair
{
    // 通用实现...
};

// 偏特化：第二个类型是int
template <typename T>
class Pair<T, int>
{
    // 特殊实现...
};

// 完全特化：两个类型都是int
template <>
class Pair<int, int>
{
    // 特殊实现...
};

// 主模板的重要性
// 1.模板匹配顺序：
//      编译器首先尝试匹配完全特化
//      然后尝试匹配最特殊的偏特化
//      如果没有匹配的特化，则使用主模板
// 2.SFINAE (Substitution Failure Is Not An Error)：
//      主模板可以通过SFINAE技术与特化配合，实现编译时的条件选择
// 3.模板元编程：
//      主模板通常作为递归终止条件的基础

// 主模板的声明与定义
// 主模板可以只有声明而没有定义，这在某些情况下很有用：
// 只声明主模板
template <typename T>
class SpecializedOnly;

// 只提供特化的实现
template <>
class SpecializedOnly<int>
{
    // 实现...
};

// 使用未特化的主模板会导致链接错误
// SpecializedOnly<double> obj;  // 错误！

// 主模板与默认模板参数
// 主模板可以为部分或全部模板参数提供默认值：
template <typename T = int, int Size = 10>
class DefaultedArray
{
    T elements[Size];
    // ...
};

// 可以不提供任何参数
DefaultedArray<> array; // 等同于DefaultedArray<int, 10>

// 主模板的限制
// 函数模板不能有偏特化，只能有完全特化
// 主模板必须在任何特化之前声明
// 主模板和特化必须在同一命名空间中
